@file:Suppress("NOTHING_TO_INLINE", "unused")
package com.hzw.core.ctx

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

inline fun <reified A : Activity> Fragment.start(configIntent: Intent.() -> Unit = {}) {
    requireContext().start<A>(configIntent)
}


inline fun Fragment.start(action: String, configIntent: Intent.() -> Unit = {}) {
    requireContext().start(action, configIntent)
}


inline fun <reified A : Activity> Fragment.start(vararg params: Pair<String, Any?>) {
    requireContext().start<A>(params = params)
}

inline fun Fragment.start(action: String, vararg params: Pair<String, Any?>) {
    requireContext().start(action = action, params = params)
}

inline fun Fragment.putArg(key: String, value: Any?) {
    val args = arguments ?: Bundle().also {
        arguments = it
    }
    args.put(key, value)
}

inline fun Fragment.putArgs(vararg params: Pair<String, Any?>) {
    val args = arguments ?: Bundle().also {
        arguments = it
    }
    params.forEach {
        args.put(it.first, it.second)
    }
}

fun <T : Any> Fragment.arg() = FragmentArgDelegate as ReadWriteProperty<Fragment, Any>

fun <T> Fragment.argOrNull(): ReadWriteProperty<Fragment, T?> =
    FragmentArgOrNullDelegate as ReadWriteProperty<Fragment, T?>

fun <T : Any> Fragment.argOrDefault(defaultValue: T): ReadWriteProperty<Fragment, T> =
    FragmentArgOrDefaultDelegate(defaultValue)

fun <T : Any> Fragment.argOrElse(defaultValue: () -> T): ReadWriteProperty<Fragment, T> =
    FragmentArgOrElseDelegate(defaultValue)

private object FragmentArgDelegate : ReadWriteProperty<Fragment, Any> {
    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: Any) {
        thisRef.putArg(property.name, value)
    }

    override fun getValue(thisRef: Fragment, property: KProperty<*>): Any {
        val key = property.name
        val args = thisRef.arguments ?: error("Fragment还没有设置Arguments")
        return checkNotNull(args.get(key)) {
            "Arguments($key)中值为空"
        }
    }
}

private object FragmentArgOrNullDelegate : ReadWriteProperty<Fragment, Any?> {

    override operator fun getValue(thisRef: Fragment, property: KProperty<*>): Any? {
        return thisRef.arguments?.get(property.name)
    }

    override operator fun setValue(thisRef: Fragment, property: KProperty<*>, value: Any?) {
        thisRef.putArg(property.name, value)
    }
}

private class FragmentArgOrDefaultDelegate<T : Any>(private val defaultValue: T) :
    ReadWriteProperty<Fragment, T> {

    override operator fun getValue(thisRef: Fragment, property: KProperty<*>): T {
        @Suppress("UNCHECKED_CAST")
        return thisRef.arguments?.get(property.name) as T? ?: defaultValue
    }

    override operator fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) {
        thisRef.putArg(property.name, value)
    }
}

private class FragmentArgOrElseDelegate<T : Any>(private val defaultValue: () -> T) :
    ReadWriteProperty<Fragment, T> {

    override operator fun getValue(thisRef: Fragment, property: KProperty<*>): T {
        @Suppress("UNCHECKED_CAST")
        return thisRef.arguments?.get(property.name) as T? ?: defaultValue()
    }

    override operator fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) {
        thisRef.putArg(property.name, value)
    }
}